package cn.assumejson.springframework.beans.factory.support;

import cn.assumejson.springframework.beans.factory.BeansException;
import cn.assumejson.springframework.beans.factory.DisposableBean;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.Method;

/**
 * Spring 对销毁，做成了一个整体，抽取出一个适配器，做统一处理。因为Spring 是需要在正常的关闭下（容器关闭），才会调用销毁方法的
 * 并且销毁情况有很多种。所以需要一个单独的类来统一管理
 *
 * @author Mr. Li
 * @version 1.0
 * @since 1.0 2021/12/1 6:52
 */
public class DisposableBeanAdapter implements DisposableBean {

    private final String beanName;

    private String destroyMethodName;

    private final Object bean;

    public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition bd) {
        this.bean = bean;
        this.beanName = beanName;
        this.destroyMethodName = bd.getDestroyMethodName();
    }

    @Override
    public void destroy() throws Exception {
        // 1. 实现接口 DisposableBean
        if (bean instanceof DisposableBean) {
            ((DisposableBean) bean).destroy();
        }

        // 2. 配置信息 destroy-method {判断是为了避免二次执行销毁}
        if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) {
            Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
            if (ObjectUtil.isNull(destroyMethod)) {
                throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
            }
            destroyMethod.invoke(bean);
        }

    }
}
